/*
 *MIT License
 *
 *Copyright (c) 2019 chenshuai cs4380@163.com
 *
 *Permission is hereby granted, free of charge, to any person obtaining a copy
 *of this software and associated documentation files (the "Software"), to deal
 *in the Software without restriction, including without limitation the rights
 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *copies of the Software, and to permit persons to whom the Software is
 *furnished to do so, subject to the following conditions:
 *
 *The above copyright notice and this permission notice shall be included in all
 *copies or substantial portions of the Software.
 *
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *SOFTWARE.
 */

package com.cs.cslc.auth.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cs.cslc.auth.dto.PhoneInfoResultDTO;
import com.cs.cslc.auth.dto.WxAccessTokenDTO;
import com.cs.cslc.common.constant.WxUrlsConstant;
import com.cs.cslc.common.util.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;


/**
 * MemberAuthController 微信相关接口操作.
 *
 * @author cs4380 https://gitee.com/xhbug_cs4380  cs4380@163.com
 * @version 1.0
 * @since 2024-03-8
 */
@Slf4j
@Service
public class WxService {

    @Value("${wx.appId}")
    private String appId;

    @Value("${wx.secret}")
    private String secret;

    /**
     * 获取accessToken,缓存到内存，1.5个小时更新一次缓存
     */
    @Cacheable(cacheNames = "accessTokenCache", cacheManager = "accessTokenCacheManager")
    public WxAccessTokenDTO getAccessToken() {
        StringBuilder sendData = new StringBuilder();
        sendData.append("?grant_type=").append("client_credential")
                .append("&appid=").append(appId)
                .append("&secret=").append(secret);
        // access_token 的有效期目前为 2 个小时
        String response = HttpUtils.sendJsonGet(WxUrlsConstant.TOKEN_URL, sendData.toString());
        return JSON.parseObject(response, WxAccessTokenDTO.class);
    }

    /**
     * 获取用户手机号
     */
    public String getUserPhone(String code) {
        try {
            WxAccessTokenDTO wxAccessTokenDTO = this.getAccessToken();
            JSONObject personJsonObject = new JSONObject();
            personJsonObject.put("code", code);

            String response = HttpUtils.sendJsonPost(WxUrlsConstant.PHONE_URL + "?access_token=" + wxAccessTokenDTO.getAccess_token(), personJsonObject.toJSONString());
            if (StringUtils.isEmpty(response)) {
                log.error("微信获取手机号异常: response 解析异常");
                return null;
            }
            PhoneInfoResultDTO phoneInfoResultDTO = JSON.parseObject(response, PhoneInfoResultDTO.class);
            if (null == phoneInfoResultDTO) {
                log.error("微信获取手机号异常: phoneInfoResultDTO 解析异常");
                return null;
            }
            if (0 == phoneInfoResultDTO.getErrcode()) {
                return phoneInfoResultDTO.getPhone_info().getPhoneNumber();
            } else {
                log.error("微信获取手机号异常:{}", JSONObject.toJSONString(phoneInfoResultDTO));
                return null;
            }
        } catch (RuntimeException e) {
            log.error("微信获取手机号异常", e);
        }
        return null;
    }

    /**
     * 发送订阅消息
     *
     * @param templateId 订阅模板id
     * @param page       点击模板卡片后的跳转页面
     * @param touser     接收者（用户）的 openid
     * @param data       模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }的object
     */
    public String sendSubscribeMessage(String templateId, String page, String touser, JSONObject data) {
        try {
            WxAccessTokenDTO wxAccessTokenDTO = this.getAccessToken();
            JSONObject personJsonObject = new JSONObject();
            // 订阅模板id
            personJsonObject.put("template_id", templateId);

            // 点击模板卡片后的跳转页面
            if (StringUtils.isNotBlank(page)) {
                personJsonObject.put("page", page);
            }
            // 接收者（用户）的 openid
            personJsonObject.put("touser", touser);

            // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }的object
            personJsonObject.put("data", data);


            String response = HttpUtils.sendJsonPost(WxUrlsConstant.SUBSCRIBE_MESSAGE_URL + "?access_token=" + wxAccessTokenDTO.getAccess_token(), personJsonObject.toJSONString());
            if (StringUtils.isEmpty(response)) {
                log.error("发送订阅消息异常: response 解析异常");
                return null;
            }
            PhoneInfoResultDTO phoneInfoResultDTO = JSON.parseObject(response, PhoneInfoResultDTO.class);
            if (null == phoneInfoResultDTO) {
                log.error("发送订阅消息异常: phoneInfoResultDTO 解析异常");
                return null;
            }
            if (0 == phoneInfoResultDTO.getErrcode()) {
                return phoneInfoResultDTO.getPhone_info().getPhoneNumber();
            } else {
                log.error("发送订阅消息异常:{}", JSONObject.toJSONString(phoneInfoResultDTO));
                return null;
            }
        } catch (RuntimeException e) {
            log.error("发送订阅消息异常", e);
        }
        return null;
    }

    /**
     * 发送订阅消息
     *
     * @param templateId 订阅模板id
     * @param page       点击模板卡片后的跳转页面
     * @param touser     接收者（用户）的 openid
     * @param data       模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }的object
     */
    public String sendSubscribeMessage2(String templateId, String page, String touser, JSONObject data) {
        try {
            WxAccessTokenDTO wxAccessTokenDTO = this.getAccessToken();
            JSONObject personJsonObject = new JSONObject();
            // 订阅模板id
            personJsonObject.put("template_id", templateId);

            // 点击模板卡片后的跳转页面
            if (StringUtils.isNotBlank(page)) {
                personJsonObject.put("page", page);
            }
            // 接收者（用户）的 openid
            personJsonObject.put("touser", touser);

            // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }的object
            personJsonObject.put("data", data);


            String response = HttpUtils.sendJsonPost(WxUrlsConstant.SUBSCRIBE_MESSAGE_URL + "?access_token=" + wxAccessTokenDTO.getAccess_token(), personJsonObject.toJSONString());
            if (StringUtils.isEmpty(response)) {
                log.error("发送订阅消息异常: response 解析异常");
                return null;
            }
            PhoneInfoResultDTO phoneInfoResultDTO = JSON.parseObject(response, PhoneInfoResultDTO.class);
            if (null == phoneInfoResultDTO) {
                log.error("发送订阅消息异常: phoneInfoResultDTO 解析异常");
                return null;
            }
            if (0 == phoneInfoResultDTO.getErrcode()) {
                return phoneInfoResultDTO.getPhone_info().getPhoneNumber();
            } else {
                log.error("发送订阅消息异常:{}", JSONObject.toJSONString(phoneInfoResultDTO));
                return null;
            }
        } catch (RuntimeException e) {
            log.error("发送订阅消息异常", e);
        }
        return null;
    }
}
